package com.xyy.saas.payment.adpater.jd.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.*;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * HttpClient 通信工具类 ，支持http和https通信
 * https 通信过程中目前是采取信任所有证书方式通信，存在安全隐患
 * 通过读取JKS证书容器库的方式可以实现信任库的建立，见方法 trustSslSocketFactory()
 * 其他方式的证书，实现信任库，需要后续考虑
 */
@Slf4j
public class JDWyHttpClientUtil {
    public static final String CHARSET = "UTF-8";
    /** 连接超时时间 **/
    public final static int CONNECTION_TIMEOUT = 5000;
    /** 数据读取等待时间 **/
    public final static int SO_TIMEOUT = 15000;
    /** 默认的http 通信接口 **/
    public final static int DEFAULT_HTTP_PORT = 80;
     /** 默认的https 通信接口 **/
    public final static int DEFAULT_HTTPS_PORT = 443;

    public String postUrlWithParams(String logPrefix, String url, Map params) {
        return postUrlWithParams(logPrefix, url, params, CHARSET);
    }

    /**
     * 发送post请求 ，带有参数
     */
    public String postUrlWithParams(String logPrefix, String url, Map params, String encoding) {
        String encode = CHARSET;
        if (!StringUtils.isEmpty(encoding)) {
            encode = encoding;
        }
        log.info("{} HttpClient方式调用开始", logPrefix);
        DefaultHttpClient httpclient = new DefaultHttpClient();
        HttpPost httpost = new HttpPost(url);
        // 添加参数
        List<NameValuePair> nvps = new ArrayList<>();
        if (params != null && params.keySet().size() > 0) {
            Iterator iterator = params.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry) iterator.next();
                nvps.add(new BasicNameValuePair((String) entry.getKey(), (String) entry.getValue()));
            }
        }
        StringBuilder sb = new StringBuilder();
        BufferedReader br = null;
        try {
            httpost.setEntity(new UrlEncodedFormEntity(nvps, encode));
            HttpResponse response = httpclient.execute(httpost);
            // 充值业务跳转页面放在header里需要从header里获取跳转地址，apimock页面进行跳转
            Header[] header = response.getHeaders(HttpHeaders.LOCATION);
            if (header.length > 0) {
                String str = header[0].getValue();
                if (!StringUtils.isBlank(str) && str.indexOf("http") > -1) {
                    return str;
                }
            }
            HttpEntity entity = response.getEntity();
            br = new BufferedReader(new InputStreamReader(entity.getContent(), encode));
            String s;
            while ((s = br.readLine()) != null) {
                sb.append(s);
            }
            return sb.toString();
        } catch (UnsupportedEncodingException e) {
            log.error("{} 创建通信异常", logPrefix, e);
            throw new RuntimeException("创建通信异常", e);
        } catch (IOException e) {
            log.error("{} 读取流文件异常 ", logPrefix, e);
            throw new RuntimeException("读取流文件异常 ", e);
        } catch (Exception e) {
            log.error("{} 通讯未知系统异常", logPrefix, e);
            throw new RuntimeException("通讯未知系统异常", e);
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (Exception e) {
                    log.error("{} 关闭br异常", logPrefix, e);
                }
            }
        }
    }

    public String postSSLUrlWithParams(String logPrefix, String url, Map params) {
        return postSSLUrlWithParams(logPrefix, url, params, CHARSET);
    }

    /**
     * 发送https post请求 ，带有参数
     */
    public String postSSLUrlWithParams(String logPrefix, String url, Map params, String encoding) {
        String encode = CHARSET;
        if (!StringUtils.isEmpty(encoding)) {
            encode = encoding;
        }
        //log.info("{} httpClient invocation", logPrefix);
        DefaultHttpClient httpclient = new DefaultHttpClient();
        HttpPost httpost = new HttpPost(url);
        // 添加参数
        List<NameValuePair> nvps = new ArrayList<>();
        if (params != null && params.keySet().size() > 0) {
            Iterator iterator = params.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry) iterator.next();
                nvps.add(new BasicNameValuePair((String) entry.getKey(),
                        (String) entry.getValue()));
            }
        }
        StringBuilder sb = new StringBuilder();
        BufferedReader br = null;
        try {
            httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, CONNECTION_TIMEOUT);
            httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, SO_TIMEOUT);
            httpclient.getConnectionManager().getSchemeRegistry().register(new Scheme("http", DEFAULT_HTTP_PORT, PlainSocketFactory.getSocketFactory()));
            httpclient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", DEFAULT_HTTPS_PORT, getTrustSSLSocketFactory(logPrefix)));
            httpost.setEntity(new UrlEncodedFormEntity(nvps, encode));
            HttpResponse response = httpclient.execute(httpost);
            HttpEntity entity = response.getEntity();
            br = new BufferedReader(new InputStreamReader(entity.getContent(), encode));
            String s;
            while ((s = br.readLine()) != null) {
                sb.append(s);
            }
            return sb.toString();

        } catch (UnsupportedEncodingException e) {
            log.error("{} 创建通信异常", logPrefix, e);
            throw new RuntimeException("创建通信异常", e);
        } catch (IOException e) {
            log.error("{} 读取流文件异常 ", logPrefix, e);
            throw new RuntimeException("读取流文件异常 ", e);
        } catch (Exception e) {
            log.error("{} 通讯未知系统异常 ", logPrefix, e);
            throw new RuntimeException("通讯未知系统异常 ", e);
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (Exception e) {
                    log.error("{} 关闭br异常", logPrefix, e);
                }
            }
        }
    }

    public SSLSocketFactory getTrustSSLSocketFactory(String logPrefix) {
        SSLSocketFactory socketFactory;
        try {
            socketFactory = new SSLSocketFactory((chain, authType) -> true, new AllowAllHostnameVerifier());
            return socketFactory;
        } catch (Exception e) {
            log.error("{} 获取可信任的socktFactory出现异常: ", logPrefix, e.getMessage());
        }
        return SSLSocketFactory.getSocketFactory();
    }

}